#pragma once
#ifndef TCPCONNECTION_H
#define TCPCONNECTION_H
#include "NonCopyable.h"
#include <memory>
#include <string>
#include <atomic>
#include "Callbacks.h"
#include "Buffer.h"
#include "TimeStamp.h"
#include "InetAddress.h"
namespace mymuduo {

class Channel;
class EventLoop;
class Socket;

/*
 * TcpServer => Acceptor => 有一个新用户连接，通过 acceptor 函数拿到 connfd
 * => TcpConnection 设置回调 => Channel => Poller => Channel 回调操作
 */
class TcpConnection : NonCopyable, public std::enable_shared_from_this<TcpConnection> {

public:
    TcpConnection(EventLoop *loop, const std::string &name,
                  int sockfd, const InetAddress& localAddr, const InetAddress& peerAddr);
    ~TcpConnection();

    EventLoop* getLoop() const {return loop_;}
    const std::string& name() const {return name_;}
    const InetAddress& localAddr() const {return localAddr_;}
    const InetAddress& peerAddr() const {return peerAddr_;}

    bool connected() const {return state_ == kConnected;}

    // 发送数据
    void send(const std::string& buf);
    // 关闭连接
    void shutdown();

    void setConnectionCallback(const ConnectionCallback& cb)
    { connectionCallback_ = cb; }
  
    void setMessageCallback(const MessageCallback& cb)
    { messageCallback_ = cb; }
  
    void setWriteCompleteCallback(const WriteCompleteCallback& cb)
    { writeCompleteCallback_ = cb; }
  
    void setHighWaterMarkCallback(const HighWaterMarkCallback& cb, size_t highWaterMark)
    { highWaterMarkCallback_ = cb; highWaterMark_ = highWaterMark; }

    // 建立连接
    void connectEstablished();   
    // 销毁连接
    void connectDestroyed(); 

    void setCloseCallback(const CloseCallback& cb) {closeCallback_ = cb;}
    
    
private:
    enum StateE {kDisconnected, kConnecting, kConnected, kDisconnecting};
    void setState(StateE state) {state_ = state;}
    void handleRead(TimeStamp receiveTime);
    void handleWrite();
    void handleClose();
    void handleError();

    void sendInLoop(const void* message, size_t len);
    void shutdownInLoop();

    EventLoop* loop_; // 这里绝对不是 baseloop，因为 TcpConnection 都是在 subloop 管理的
    const std::string name_;
    std::atomic_int state_;
    bool reading_;

    std::unique_ptr<Socket> socket_;
    std::unique_ptr<Channel> channel_;
    
    const InetAddress localAddr_;
    const InetAddress peerAddr_;

    ConnectionCallback connectionCallback_; // 有新连接时的回调
    MessageCallback messageCallback_; // 有读写消息时的回调
    WriteCompleteCallback writeCompleteCallback_; // 消息发送完以后的回调
    CloseCallback closeCallback_; // 关闭连接以后的回调
    HighWaterMarkCallback highWaterMarkCallback_; // 高水位回调

    size_t highWaterMark_;
    Buffer inputBuffer_;
    Buffer outputBuffer_;
};  

}

#endif